package gmcp

import (
	"bufio"
	"encoding/json"
	"fmt"
	"log"
	"os"
)

type mcpServer struct {
	mcpInfo *MCPInformation
	tools   map[string]Tool
}

func NewServer(name, version string) *mcpServer {
	return &mcpServer{
		tools: make(map[string]Tool),
		mcpInfo: &MCPInformation{
			ProtocolVersion: "2025-06-18",
			Capabilities: Capabilities{
				Tools: struct{}{},
			},
			ServerInfo: ServerInfo{
				Name:    name,
				Version: version,
			},
		},
	}
}

func (s *mcpServer) RunWithScanner() {
	scanner := bufio.NewScanner(os.Stdin)
	encoder := json.NewEncoder(os.Stdout)

	log.SetOutput(os.Stderr)

	log.Println("MCP Server started")

	// 主循环：读取请求并处理
	for scanner.Scan() {
		line := scanner.Text()

		if line == "" {
			continue
		}

		// 解析 JSON-RPC 请求
		var request JSONRPCRequest
		if err := json.Unmarshal([]byte(line), &request); err != nil {
			log.Printf("Invalid JSON: %v\n", err)
			continue
		}

		log.Printf("Received request: id=%v body=%v\n", request.ID, line)

		// 处理请求
		response := s.HandleRequest(request)

		// 输出响应
		if err := encoder.Encode(response); err != nil {
			log.Printf("Failed to encode response: %v\n", err)
			continue
		}

		jsonBody, _ := json.Marshal(response)

		log.Printf("Sent response: id=%v body=%v\n", response.ID, string(jsonBody))
	}

	if err := scanner.Err(); err != nil {
		log.Printf("Scanner error: %v\n", err)
	}

	log.Println("MCP Server stopped")
}

func (s *mcpServer) HandleRequest(req JSONRPCRequest) *JSONRPCResponse {
	switch req.Method {
	case "initialize":
		return s.handleInitialize(req)
	case "tools/list":
		return s.handleToolsList(req)
	case "tools/call":
		return s.handleToolsCall(req)
	default:
		return &JSONRPCResponse{
			JSONRPC: "2.0",
			ID:      req.ID,
			Error: &RPCError{
				Code:    -32601,
				Message: fmt.Sprintf("Method not found: %s", req.Method),
			},
		}
	}
}

func (s *mcpServer) RegisterTool(tool Tool) {
	s.tools[tool.Name] = tool
}

func (s *mcpServer) handleInitialize(req JSONRPCRequest) *JSONRPCResponse {
	return &JSONRPCResponse{
		JSONRPC: "2.0",
		ID:      req.ID,
		Result:  s.mcpInfo,
	}
}

func (s *mcpServer) handleToolsList(req JSONRPCRequest) *JSONRPCResponse {
	tools := make([]Tool, 0, len(s.tools))

	for _, tool := range s.tools {
		tools = append(tools, tool)
	}

	return &JSONRPCResponse{
		JSONRPC: "2.0",
		ID:      req.ID,
		Result: ToolsListResult{
			Tools: tools,
		},
	}
}

func (s *mcpServer) handleToolsCall(req JSONRPCRequest) *JSONRPCResponse {
	var params ToolCallParams

	if err := json.Unmarshal(req.Params, &params); err != nil {
		return &JSONRPCResponse{
			JSONRPC: "2.0",
			ID:      req.ID,
			Error: &RPCError{
				Code:    -32602,
				Message: fmt.Sprintf("Invalid params: %v", err),
			},
		}
	}

	if tool, ok := s.tools[params.Name]; ok {
		result, err := tool.Handle(params.Arguments)

		if err != nil {
			return &JSONRPCResponse{
				JSONRPC: "2.0",
				ID:      req.ID,
				Error: &RPCError{
					Code:    -32603,
					Message: err.Error(),
				},
			}
		}

		return &JSONRPCResponse{
			JSONRPC: "2.0",
			ID:      req.ID,
			Result:  result,
		}
	}

	return &JSONRPCResponse{
		JSONRPC: "2.0",
		ID:      req.ID,
		Error: &RPCError{
			Code:    -32603,
			Message: fmt.Sprintf("Unknown tool: %s", params.Name),
		},
	}
}
